﻿using System.Collections.Generic;
using UnityEngine;

namespace Battle
{
    public class Fsm
    {
        protected FsmContext context;
        protected FsmState curState = FsmState.None;
        protected FsmState lstState = FsmState.None;
		protected FsmState defaultState = FsmState.None;
        protected readonly Dictionary<FsmState, BaseState> states = new Dictionary<FsmState, BaseState>();
        protected readonly List<BaseTransition> transitions = new List<BaseTransition>(); 


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="initState"></param>
        /// <param name="hero"></param>
        public Fsm()
        {
            context = new FsmContext(this);
        }

		public void OnInit()
		{
			curState = defaultState;
		}

        public void Bind(Actor a, Behaviour b)
        {
            context.Actor = a;
            context.Behaviour = b;
        }

		public void SetDefault(FsmState f)
		{
			defaultState = f;
		}

        public void AddState(FsmState f, BaseState s)
        {
			if(states.Count<=0)
				defaultState = f;
            if(!states.ContainsKey(f))
                states[f] = s;
        }
        public void AddTransition(BaseTransition t)
        {
            transitions.Add(t);
        }


        /// <summary>
        /// Get Last State
        /// </summary>
        /// <returns>last fsm state</returns>
        public FsmState LastState
        {
            get { return lstState; }
        }


        /// <summary>
        /// Get Current State
        /// </summary>
        /// <returns>current fsm state</returns>
        public FsmState CurState
        {
            get { return curState; }
        }

        public void Tick(float delta)
        {
            context.Delta = delta;


            FsmState nxt = FsmState.None;
            //global transition
            for (int i = 0; i < transitions.Count; ++i)
            {
                if (transitions[i].Transite(context, ref nxt))
                {
                    ChangeState(nxt);
                }
            }

            //state transition
            nxt = FsmState.None;
            if (states[curState].OnTransition(context, ref nxt))
            {
                ChangeState(nxt);
            }

            //update state
			Debug.Log(Time.realtimeSinceStartup+"----Tick---->"+curState);
            states[curState].OnUpdate(context);

        }

        /// <summary>
        /// Change Fsm State
        /// </summary>
        /// <param name="nxtState"></param>
        protected void ChangeState(FsmState nxtState)
        {
            if (nxtState == FsmState.None || curState == nxtState)
                return;
			Debug.Log(Time.realtimeSinceStartup+"----To---->"+nxtState);
            if (curState != FsmState.None)
            {
                states[curState].ExitState(context);
            }
            lstState = curState;
            curState = nxtState;
            states[curState].EnterState(context);
        }
    }

}


